package service

import (
	"github.com/beego/beego/v2/client/orm"
	"github.com/duke-git/lancet/v2/slice"
	"net/url"
	"strconv"
)

// Pagination struct
type Pagination struct {
	//当前页
	PageNum int `json:"pageNum"`
	//每页数量
	PageSize int `json:"pageSize"`
	//数据总数
	Total int         `json:"total"`
	List  interface{} `json:"list"`
}

// Paginate 分页
func (pagination *Pagination) Paginate(ps orm.QuerySeter, parameters url.Values) orm.QuerySeter {
	//当前页
	var page int
	pageStr := parameters.Get("pageNum")
	if pageStr == "" {
		page = 1
	} else {
		page, _ = strconv.Atoi(pageStr)
	}

	if page < 1 {
		page = 1
	}

	var pageSize int
	pageSizeStr := parameters.Get("pageSize")
	if pageSizeStr == "" {
		pageSize = 10
	} else {
		pageSize, _ = strconv.Atoi(pageSizeStr)
	}

	if pageSize < 1 {
		pageSize = 1
	}

	pagination.PageNum = page
	pagination.PageSize = pageSize
	total, err := ps.Count()
	if err != nil {
		pagination.Total = 0
	}

	pagination.Total = int(total)
	return ps.Limit(pagination.PageSize, (pagination.PageNum-1)*pagination.PageSize)
}

type BaseService struct {
	//可搜索字段
	SearchField []string
	//可作为条件的字段
	WhereField []string
	//分页
	Pagination Pagination
}

// Paginate 分页处理
func (bs *BaseService) Paginate(seter orm.QuerySeter, parameters url.Values) orm.QuerySeter {
	var pagination Pagination
	qs := pagination.Paginate(seter, parameters)
	bs.Pagination = pagination
	return qs
}

// ScopeWhere 查询处理
func (bs *BaseService) ScopeWhere(qs orm.QuerySeter, parameters url.Values, others ...CondFunc) orm.QuerySeter {
	//关键词like搜索
	keywords := parameters.Get("keywords")
	cond := orm.NewCondition()
	if keywords != "" && len(bs.SearchField) > 0 {
		for _, v := range bs.SearchField {
			cond = cond.Or(v+"__icontains", keywords)
		}
	}

	//字段条件查询
	if len(bs.WhereField) > 0 && len(parameters) > 0 {
		for k, v := range parameters {
			if v[0] != "" && slice.Contain(bs.WhereField, k) {
				cond = cond.And(k, v[0])
			}
		}
	}

	// 默认只查询有效的数据
	//if !parameters.Has("status") {
	//	cond = cond.And("status__gte", schema.Enabled)
	//}

	// 添加外部条件
	for _, other := range others {
		cond = other(cond)
	}

	//将条件语句拼装到主语句中
	qs = qs.SetCond(cond)

	//排序
	order := parameters.Get("order")
	if order == "" {
		order = "id"
	}
	by := parameters.Get("by")
	if order != "" {
		if by == "" {
			by = "-"
		} else {
			if by == "asc" {
				by = ""
			} else {
				by = "-"
			}
		}
	}
	//排序
	qs = qs.OrderBy(by + order)

	return qs
}

type CondFunc func(*orm.Condition) *orm.Condition

// PaginateAndScopeWhere 分页和查询合并，多用于首页列表展示
func (bs *BaseService) PaginateAndScopeWhere(seter orm.QuerySeter, parameters url.Values, others ...CondFunc) orm.QuerySeter {
	return bs.Paginate(bs.ScopeWhere(seter, parameters, others...), parameters)
}
